#include "stdafx.h"
#include "FCFile.h"
#include "GTKHost.h"
#include "GTKPaint.h"
#include "MainFrame.h"
#include <cairo.h>
#include <gtk/gtk.h>
#include "DataCenter.h"

FCNative *m_native = 0;
GTKHost *m_host = 0;
GTKPaint *m_paint = 0;
int m_mouseDownButton = 0;
GtkIMContext *m_context = 0;
int m_lastClicks = 0;

static bool m_hasInput = false;

gboolean on_key_release_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data) {  
	m_native->onKeyUp((int)event->keyval);
	m_hasInput = false;
    return FALSE;  
}  

gboolean key_callback(GtkWidget *widget,
                             GdkEventKey *event,
                             gpointer user_data) {
	m_hasInput = true;
	if (event->state & GDK_SHIFT_MASK) {  
		m_host->m_isShift = true;
	}else{
		m_host->m_isShift = false;
	}
	if (event->state & GDK_MOD1_MASK) {  
		m_host->m_isAlt = true;
	}else{
		m_host->m_isAlt = false;
	}
	if (event->state & GDK_CONTROL_MASK) {  
		m_host->m_isCtrl = true;
	}else{
		m_host->m_isCtrl = false;
	}
	int keyCode = (int)event->keyval;
	if(keyCode == 65288){
		keyCode = 8;
	}else if(keyCode == 65361){
		keyCode = 37;
	}else if(keyCode == 65362){
		keyCode = 38;
	}else if(keyCode == 65363){
		keyCode = 39;
	}else if(keyCode == 65364){
		keyCode = 40;
	}else if(keyCode == 65307){
		keyCode = 27;
	}else if(keyCode == 65293){
		keyCode = 13;
		m_native->onChar(keyCode);
	}else if(keyCode == 65289){
		keyCode = '\t';
		m_native->onChar(keyCode);
	}
	//shift
	else if(keyCode == 65505){

	}
	//alt
	else if(keyCode == 65513){

	}
	//ctrl
	else if(keyCode == 65507){

	}
	else{
		if(keyCode <= 256){
			m_native->onChar(keyCode);
		}
	}
	m_native->onKeyDown(keyCode);
	return gtk_im_context_filter_keypress(m_context, event);
}

gboolean gtk_entry_commit_cb (GtkIMContext *context, const guchar  *str, gpointer data)
{
	if(!m_hasInput){
		lstring inputText = (char*)str;
		if((int)inputText.length() > 0){
			FCView *focusedView = m_native->getFocusedView();
			if(focusedView){
				FCTextBox *textBox = dynamic_cast<FCTextBox*>(focusedView);
				if(textBox && !textBox->m_readOnly){
					String insertText = FCTran::stringToString(inputText);
					//iTextBox::onChar2(textBox, insertText);
				}
			}
		}
	}
	return FALSE;
}

gboolean deal_mouse_press(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	if(m_context){
		g_object_unref(m_context);
	}
	GdkWindow *gdk_window = gtk_widget_get_window(GTK_WIDGET(m_host->m_window));
	m_context = gtk_im_multicontext_new();
	gtk_im_context_set_client_window(m_context, gdk_window);
	g_signal_connect(m_context, "commit", G_CALLBACK(gtk_entry_commit_cb), NULL);
	gtk_widget_grab_focus(widget);
	gtk_im_context_focus_in(m_context);
	FCPoint mp = {(int)event->x, (int)event->y};
	m_host->m_touchPoint = mp;
	FCTouchInfo touchInfo;
	touchInfo.m_clicks = 1;
	m_mouseDownButton = 0;
	switch(event->button){	
		case 1:
			touchInfo.m_firstTouch = true;
			touchInfo.m_firstPoint = mp;
			m_mouseDownButton = 1;
			break;
		case 3:
			touchInfo.m_secondTouch = true;
			touchInfo.m_secondPoint = mp;
			m_mouseDownButton = 2;
			break;
	}
 
	if(event->type == GDK_2BUTTON_PRESS){
		touchInfo.m_clicks = 2;
	}
	m_lastClicks = touchInfo.m_clicks;
	m_native->onMouseDown(touchInfo);
	return FALSE;
}
 
gboolean deal_mouse_release(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	FCPoint mp = {(int)event->x, (int)event->y};
	m_host->m_touchPoint = mp;
	FCTouchInfo touchInfo;
	touchInfo.m_clicks = m_lastClicks;
	m_mouseDownButton = 0;
	switch(event->button){	
		case 1:
			touchInfo.m_firstTouch = true;
			touchInfo.m_firstPoint = mp;
			break;
		case 3:
			touchInfo.m_secondTouch = true;
			touchInfo.m_secondPoint = mp;
			break;
	}
	m_native->onMouseUp(touchInfo);
	return FALSE;
}
 
gboolean deal_motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
{
	FCPoint mp = {(int)event->x, (int)event->y};
	m_host->m_touchPoint = mp;
	FCTouchInfo touchInfo;
	if(m_mouseDownButton == 1){
		touchInfo.m_firstTouch = true;
		touchInfo.m_firstPoint = mp;
		touchInfo.m_clicks = 1;
	}else if(m_mouseDownButton == 2){
		touchInfo.m_secondTouch = true;
		touchInfo.m_secondPoint = mp;
		touchInfo.m_clicks = 1;
	}else{
		touchInfo.m_firstPoint = mp;
	}
	m_native->onMouseMove(touchInfo);
	return FALSE;
}

gboolean on_draw_event(GtkWidget* widget, cairo_t* cr) {
	if(m_paint){
		int li_width;
		int li_height;
		m_paint->m_cr = cr;
		li_width = gtk_widget_get_allocated_width(widget);
		li_height = gtk_widget_get_allocated_height(widget);
		FCSize clientSize = {(int)li_width, (int)li_height};
		m_host->m_clientSize = clientSize;
		FCSize newSize = {(int)li_width, (int)li_height};
		FCSize oldSize = m_native->getSize();
		if(oldSize.cx != newSize.cx || oldSize.cy != newSize.cy){
			m_native->setSize(newSize);
			m_native->update();
		}
		FCRect rect = {0, 0, newSize.cx, newSize.cy};
		m_host->onPaint(rect);
	}
	return TRUE;
}

gboolean deal_timer(GtkWidget* drawing_area) {
	if(m_host){
		m_host->onTimer();
	}
	return TRUE;
}

gboolean deal_scroll(GtkWidget *widget, GdkEventScroll *event, gpointer user_data) {
    FCPoint mp = {(int)event->x, (int)event->y};
	m_host->m_touchPoint = mp;
	FCTouchInfo touchInfo;
	touchInfo.m_firstPoint = mp;
	int delta = 0;
	if(event->direction == GDK_SCROLL_UP){
		delta = 1;
	}else if(event->direction == GDK_SCROLL_DOWN){
		delta = -1;
	}
	touchInfo.m_delta = delta;
	m_native->onMouseWheel(touchInfo);
	return FALSE;
}

int main( int argc, char *argv[])
{
	GtkWidget *window;
	gtk_init(&argc, &argv);
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(window), "FaceCat");
	gtk_widget_set_size_request(window, 1200, 800);
	g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
	GtkWidget* drawingArea = gtk_drawing_area_new();
	gtk_widget_set_can_focus(drawingArea, TRUE);
	g_timeout_add(10, (GSourceFunc)deal_timer, drawingArea);
	gtk_container_add(GTK_CONTAINER(window), drawingArea);
	g_signal_connect(drawingArea, "draw", G_CALLBACK(on_draw_event), NULL);
	g_signal_connect(drawingArea, "button-press-event", G_CALLBACK(deal_mouse_press), NULL);
	g_signal_connect(drawingArea, "motion-notify-event", G_CALLBACK(deal_motion_event), NULL);
	g_signal_connect(drawingArea, "button-release-event", G_CALLBACK(deal_mouse_release), NULL);
	g_signal_connect(drawingArea, "scroll-event", G_CALLBACK(deal_scroll), NULL);
	g_signal_connect(drawingArea, "key-press-event", G_CALLBACK(key_callback), m_context);
	g_signal_connect(drawingArea, "key-release-event", G_CALLBACK(on_key_release_event), NULL);
	gtk_widget_add_events(drawingArea, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK);  
	m_native = new FCNative();
	m_paint = new GTKPaint();
	m_host = new GTKHost();
	m_native->setPaint(m_paint);
	m_host->setNative(m_native);
	m_native->setHost(m_host);
	m_host->m_drawingArea = drawingArea;
	m_paint->m_drawingArea = drawingArea;
	m_host->m_window = window;
	FCSize nativeSize = {1200, 800};
	m_native->setSize(nativeSize);
	FCRect drawRect = {0, 0, nativeSize.cx, nativeSize.cy};
	m_host->m_clientSize = nativeSize;
	MainFrame *xml = new MainFrame();
	xml->setNative(m_native);
	DataCenter::startService();
	DataCenter::startConnect();
	xml->loadFile(L"mainframe.xml", 0);
	m_native->update();
	m_native->invalidate();
	gtk_widget_show_all(window);
	gtk_main();
	return 0;
}

static int m_nativeID = 0;
static std::map<int, FCNative*> m_natives;
static bool m_initNative = false;

extern "C" int createGdiPlus(){
	std::locale::global(std::locale(""));
	if(!m_initNative){
		m_initNative = true;
	}
	m_nativeID++;
	FCNative *native = new FCNative;
	m_natives[m_nativeID] = native;
	FCPaint *paint = new GTKPaint();
	paint->setScaleFactor(1, 1);
	native->setPaint(paint);
	GTKHost *gtkHost = new GTKHost;
	native->setHost(gtkHost);
	//winHost->m_virtualMode = true;
	gtkHost->setNative(native);
	return m_nativeID;
}

/*
* 刷新视图
*/
extern "C" int invalidateView(int gID, int left, int top, int right, int bottom){
	return 1;
}

/*
* 销毁GDI+
*/
extern "C" int deleteGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		m_natives.erase(sIter);
		delete native;
		return 1;
	}else{
		return -1;
	}
}

extern "C" int addArcGdiPlus(int gID, int left, int top, int right, int bottom, float startAngle, float sweepAngle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->addArc(rect, startAngle, sweepAngle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int addBezierGdiPlus(int gID, char *strApt){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		String wStrApt = FCTran::stringToString(strApt);
		ArrayList<String> strs = FCTran::split(wStrApt, L" ");
		ArrayList<FCPoint> points;
		for(int i = 0; i < strs.size(); i++){
			ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
			if(subStrs.size() >= 2){
				points.add(FCTran::strToPoint(strs.get(i)));
			}
		}
		if(points.size() > 0){
			FCPoint *apt = new FCPoint[points.size()];
			for(int i = 0; i < points.size(); i++){
				apt[i] = points.get(i);
			}
			FCPaint *paint = sIter->second->getPaint();
			paint->addBezier(apt, points.size());
			delete[] apt;
			apt = 0;
		}
		return 1;
	}else{
		return -1;
	}
}

extern "C" int addCurveGdiPlus(int gID, char *strApt){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		String wStrApt = FCTran::stringToString(strApt);
		ArrayList<String> strs = FCTran::split(wStrApt, L" ");
		ArrayList<FCPoint> points;
		for(int i = 0; i < strs.size(); i++){
			ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
			if(subStrs.size() >= 2){
				points.add(FCTran::strToPoint(strs.get(i)));
			}
		}
		if(points.size() > 0){
			FCPoint *apt = new FCPoint[points.size()];
			for(int i = 0; i < points.size(); i++){
				apt[i] = points.get(i);
			}
			FCPaint *paint = sIter->second->getPaint();
			paint->addCurve(apt, points.size());
			delete[] apt;
			apt = 0;
		}
		return 1;
	}else{
		return -1;
	}
}

extern "C" int addEllipseGdiPlus(int gID, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint =sIter->second->getPaint();
		FCRect rect = {left, top, right, bottom};
		paint->addEllipse(rect);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int addLineGdiPlus(int gID, int x1, int y1, int x2, int y2){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->addLine(x1, y1, x2, y2);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int addRectGdiPlus(int gID, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->addRect(rect);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int addPieGdiPlus(int gID, int left, int top, int right, int bottom, float startAngle, float sweepAngle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->addPie(rect, startAngle, sweepAngle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int addTextGdiPlus(int gID, char *text, char *font, int left, int top, int right, int bottom, int width){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		paint->addText(FCTran::stringToString(text), &tFont, rect, width);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int beginExportGdiPlus(int gID, char *exportPath, int left, int top, int right, int bottom, int width){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int beginPaintGdiPlus(int gID, int hDC, int wLeft, int wTop, int wRight, int wBottom, int pLeft, int pTop, int pRight, int pBottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		FCRect wRect = {wLeft, wTop, wRight, wBottom};
		FCRect pRect = {pLeft, pTop, pRight, pBottom};
		FCSize size = {wRect.right - wRect.left, wRect.bottom - wRect.top};
		native->setSize(size);
		native->update();
		GTKPaint *gdiPlusPaint = dynamic_cast<GTKPaint*>(native->getPaint());
		gdiPlusPaint->beginPaint(hDC, wRect, pRect);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int beginPathGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->beginPath();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int clipPathGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->clipPath();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int clearCachesGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->clearCaches();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int closeFigureGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->closeFigure();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int closePathGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->closePath();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawArcGdiPlus(int gID, Long dwPenColor, float width, int style, int left, int top, int right, int bottom, float startAngle, float sweepAngle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->drawArc(dwPenColor, width, style, rect, startAngle, sweepAngle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawBezierGdiPlus(int gID, Long dwPenColor, float width, int style, char *strApt){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		String wStrApt = FCTran::stringToString(strApt);
		ArrayList<String> strs = FCTran::split(wStrApt, L" ");
		ArrayList<FCPoint> points;
		for(int i = 0; i < strs.size(); i++){
			ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
			if(subStrs.size() >= 2){
				points.add(FCTran::strToPoint(strs.get(i)));
			}
		}
		if(points.size() > 0){
			FCPoint *apt = new FCPoint[points.size()];
			for(int i = 0; i < points.size(); i++){
				apt[i] = points.get(i);
			}
			FCPaint *paint = sIter->second->getPaint();
			paint->drawBezier(dwPenColor, width, style, apt, points.size());
			delete[] apt;
			apt = 0;
		}	
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawCurveGdiPlus(int gID, Long dwPenColor, float width, int style, char *strApt){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		String wStrApt = FCTran::stringToString(strApt);
		ArrayList<String> strs = FCTran::split(wStrApt, L" ");
		ArrayList<FCPoint> points;
		for(int i = 0; i < strs.size(); i++){
			ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
			if(subStrs.size() >= 2){
				points.add(FCTran::strToPoint(strs.get(i)));
			}
		}
		if(points.size() > 0){
			FCPoint *apt = new FCPoint[points.size()];
			for(int i = 0; i < points.size(); i++){
				apt[i] = points.get(i);
			}
			FCPaint *paint = sIter->second->getPaint();
			paint->drawCurve(dwPenColor, width, style, apt, points.size());
			delete[] apt;
			apt = 0;
		}	
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawEllipseGdiPlus(int gID, Long dwPenColor, float width, int style, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->drawEllipse(dwPenColor, width, style, left, top, right, bottom);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawImageGdiPlus(int gID, String imagePath, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->drawImage(imagePath, rect);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawLineGdiPlus(int gID, Long dwPenColor, float width, int style, int x1, int y1, int x2, int y2){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->drawLine(dwPenColor, width, style, x1, y1, x2, y2);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawPathGdiPlus(int gID, Long dwPenColor, float width, int style){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->drawPath(dwPenColor, width, style);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawPieGdiPlus(int gID, Long dwPenColor, float width, int style, int left, int top, int right, int bottom, float startAngle, float sweepAngle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->drawPie(dwPenColor, width, style, rect, startAngle, sweepAngle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawPolygonGdiPlus(int gID, Long dwPenColor, float width, int style, char *strApt){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		String wStrApt = FCTran::stringToString(strApt);
		ArrayList<String> strs = FCTran::split(wStrApt, L" ");
		ArrayList<FCPoint> points;
		for(int i = 0; i < strs.size(); i++){
			ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
			if(subStrs.size() >= 2){
				points.add(FCTran::strToPoint(strs.get(i)));
			}
		}
		if(points.size() > 0){
			FCPoint *apt = new FCPoint[points.size()];
			for(int i = 0; i < points.size(); i++){
				apt[i] = points.get(i);
			}
			FCPaint *paint = sIter->second->getPaint();
			paint->drawPolygon(dwPenColor, width, style, apt, points.size());
			delete[] apt;
			apt = 0;
		}	
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawPolylineGdiPlus(int gID, Long dwPenColor, float width, int style, char *strApt){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		String wStrApt = FCTran::stringToString(strApt);
		ArrayList<String> strs = FCTran::split(wStrApt, L" ");
		ArrayList<FCPoint> points;
		for(int i = 0; i < strs.size(); i++){
			ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
			if(subStrs.size() >= 2){
				points.add(FCTran::strToPoint(strs.get(i)));
			}
		}
		if(points.size() > 0){
			FCPoint *apt = new FCPoint[points.size()];
			for(int i = 0; i < points.size(); i++){
				apt[i] = points.get(i);
			}
			FCPaint *paint = sIter->second->getPaint();
			paint->drawPolyline(dwPenColor, width, style, apt, points.size());
			delete[] apt;
			apt = 0;
		}	
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawRectGdiPlus(int gID, Long dwPenColor, float width, int style, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->drawRect(dwPenColor, width, style, left, top, right, bottom);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawRoundRectGdiPlus(int gID, Long dwPenColor, float width, int style, int left, int top, int right, int bottom, int cornerRadius){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->drawRoundRect(dwPenColor, width, style, rect, cornerRadius);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawTextGdiPlus(int gID, char *strText, Long dwPenColor, char *font, int left, int top, int right, int bottom, int width){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		paint->drawText(FCTran::stringToString(strText), dwPenColor, &tFont, rect, width);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawTextGdiPlus2(int gID, char *strText, Long dwPenColor, char *font, int left, int top, int right, int bottom, int width){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawTextWithPosGdiPlus(int gID, char *strText, Long dwPenColor, char *font, int x, int y){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		String text = FCTran::stringToString(strText);
		GTKPaint *gdiPaint = dynamic_cast<GTKPaint*>(paint);
		FCSize tSize = gdiPaint->textSize(text, &tFont, -1); 
		FCRect dRect = {x, y, x + tSize.cx, y + tSize.cy};
		gdiPaint->drawText(text, dwPenColor, &tFont, dRect, -1);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawTextWithPosGdiPlus2(int gID, char *strText, Long dwPenColor, char *font, int x, int y){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawTextAutoEllipsisGdiPlus(int gID, char *strText, Long dwPenColor, char *font, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		paint->drawTextAutoEllipsis(FCTran::stringToString(strText), dwPenColor, &tFont, rect);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int drawTextAutoEllipsisGdiPlus2(int gID, char *strText, Long dwPenColor, char *font, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		return 1;
	}else{
		return -1;
	}
}

extern "C" int endExportGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int endPaintGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->endPaint();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int excludeClipPathGdiPlus(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->excludeClipPath();
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillEllipseGdiPlus(int gID, Long dwPenColor, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->fillEllipse(dwPenColor, rect);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillGradientEllipseGdiPlus(int gID, Long dwFirst, Long dwSecond, int left, int top, int right, int bottom, int angle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->fillGradientEllipse(dwFirst, dwSecond, rect, angle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillGradientPathGdiPlus(int gID, Long dwFirst, Long dwSecond, int left, int top, int right, int bottom, int angle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->fillGradientPath(dwFirst, dwSecond, rect, angle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillGradientPolygonGdiPlus(int gID, Long dwFirst, Long dwSecond, char *strApt, int angle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		String wStrApt = FCTran::stringToString(strApt);
		ArrayList<String> strs = FCTran::split(wStrApt, L" ");
		ArrayList<FCPoint> points;
		for(int i = 0; i < strs.size(); i++){
			ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
			if(subStrs.size() >= 2){
				points.add(FCTran::strToPoint(strs.get(i)));
			}
		}
		if(points.size() > 0){
			FCPoint *apt = new FCPoint[points.size()];
			for(int i = 0; i < points.size(); i++){
				apt[i] = points.get(i);
			}
			FCPaint *paint = sIter->second->getPaint();
			paint->fillGradientPolygon(dwFirst, dwSecond, apt, points.size(), angle);
			delete[] apt;
			apt = 0;
		}	
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillGradientRectGdiPlus(int gID, Long dwFirst, Long dwSecond, int left, int top, int right, int bottom, int cornerRadius, int angle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->fillGradientRect(dwFirst, dwSecond, rect, cornerRadius, angle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillPathGdiPlus(int gID, Long dwPenColor){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->fillPath(dwPenColor);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillPieGdiPlus(int gID, Long dwPenColor, int left, int top, int right, int bottom, float startAngle, float sweepAngle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->fillPie(dwPenColor, rect, startAngle, sweepAngle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillPolygonGdiPlus(int gID, Long dwPenColor, char *strApt){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		String wStrApt = FCTran::stringToString(strApt);
		ArrayList<String> strs = FCTran::split(wStrApt, L" ");
		ArrayList<FCPoint> points;
		for(int i = 0; i < strs.size(); i++){
			ArrayList<String> subStrs = FCTran::split(strs.get(i), L",");
			if(subStrs.size() >= 2){
				points.add(FCTran::strToPoint(strs.get(i)));
			}
		}
		if(points.size() > 0){
			FCPoint *apt = new FCPoint[points.size()];
			for(int i = 0; i < points.size(); i++){
				apt[i] = points.get(i);
			}
			FCPaint *paint = sIter->second->getPaint();
			paint->fillPolygon(dwPenColor, apt, points.size());
			delete[] apt;
			apt = 0;
		}	
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillRectGdiPlus(int gID, Long dwPenColor, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->fillRect(dwPenColor, left, top, right, bottom);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int fillRoundRectGdiPlus(int gID, Long dwPenColor, int left, int top, int right, int bottom, int cornerRadius){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->fillRoundRect(dwPenColor, rect, cornerRadius);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int setClipGdiPlus(int gID, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCRect rect = {left, top, right, bottom};
		FCPaint *paint = sIter->second->getPaint();
		paint->setClip(rect);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int setLineCapGdiPlus(int gID, int startLineCap, int endLineCap){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->setLineCap(startLineCap, endLineCap);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int setOffsetGdiPlus(int gID, int offsetX, int offsetY){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		FCPoint offset = {offsetX, offsetY};
		paint->setOffset(offset);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int setOpacityGdiPlus(int gID, float opacity){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->setOpacity(opacity);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int setResourcePathGdiPlus(int gID, char *resourcePath){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->setResourcePath(FCTran::stringToString(resourcePath));
		return 1;
	}else{
		return -1;
	}
}

extern "C" int setRotateAngleGdiPlus(int gID, int rotateAngle){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->setRotateAngle(rotateAngle);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int setScaleFactorGdiPlus(int gID, double scaleFactorX, double scaleFactorY){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		paint->setScaleFactor(scaleFactorX, scaleFactorY);
		return 1;
	}else{
		return -1;
	}
}

extern "C" int textSizeGdiPlus(int gID, char *strText, char *font, int width, char *data){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		FCSize tSize = paint->textSize(FCTran::stringToString(strText), &tFont, width);
		String wStrSize = FCTran::sizeToStr(tSize);
		lstring strSize = FCTran::StringTostring(wStrSize);
		strcpy(data, strSize.c_str());
		return 1;
	}else{
		return -1;
	}
}

extern "C" int textSizeGdiPlus2(int gID, char *strText, char *font, int width, char *data){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCPaint *paint = sIter->second->getPaint();
		FCFont tFont = FCTran::strToFont(FCTran::stringToString(font));
		return 1;
	}else{
		return -1;
	}
}

extern "C" int createView(int gID, char *type, char *name){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strType = FCTran::stringToString(type);
		String strName = FCTran::stringToString(name);
		if(strType == L"textbox"){
			FCTextBox *textBox = new FCTextBox;
			textBox->setNative(native);
			textBox->setName(strName);
			native->addView(textBox);
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int removeView(int gID, char *name){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			native->removeView(view);
			delete view;
			return 1;
		}
	}
	return 0;
}

extern "C" int clearViews(int gID){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		native->clearViews();
	}
	return 0;
}

extern "C" int setAttribute(int gID, char *name, char *atrName, char *atrValue){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			String strAtrName = FCTran::stringToString(atrName);
			String strAtrValue = FCTran::stringToString(atrValue);
			view->setAttribute(strAtrName, strAtrValue);
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int setAttribute2(int gID, char *name, char *atrName, char *atrValue){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			String strAtrName = FCTran::stringToString(atrName);
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int getAttribute(int gID, char *name, char *atrName, char *atrValue){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			String strType;
			String strValue;
			String strAtrName = FCTran::stringToString(atrName);
			view->getAttribute(strAtrName, &strValue, &strType);
			if((int)strValue.length() > 0){
				lstring sValue = FCTran::StringTostring(strValue);
				strcpy(atrValue, sValue.c_str());
			}
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int paintView(int gID, char *name, int left, int top, int right, int bottom){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			FCPoint offset = native->getPaint()->getOffset();
			FCRect rect = {offset.x + left, offset.y + top, offset.x + right, offset.y + bottom};
			view->setBounds(rect);
			view->onPaint(native->getPaint(), rect);
			view->onPaintBorder(native->getPaint(), rect);
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int focusView(int gID, char *name){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			view->focus();
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int unFocusView(int gID, char *name){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			view->setFocused(false);
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int mouseDownView(int gID, char *name, int x, int y, int buttons, int clicks){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			FCTouchInfo touchInfo;
			FCPoint touchPoint = {x, y};
			touchInfo.m_clicks = clicks;
			if(buttons == 1){
				touchInfo.m_firstTouch = true;
				touchInfo.m_firstPoint = touchPoint;
			}else if(buttons == 2){
				touchInfo.m_secondTouch = true;
				touchInfo.m_secondPoint = touchPoint;
			}
			view->onTouchDown(touchInfo);
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int mouseUpView(int gID, char *name, int x, int y, int buttons, int clicks){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			FCTouchInfo touchInfo;
			FCPoint touchPoint = {x, y};
			touchInfo.m_clicks = clicks;
			if(buttons == 1){
				touchInfo.m_firstTouch = true;
				touchInfo.m_firstPoint = touchPoint;
			}else if(buttons == 2){
				touchInfo.m_secondTouch = true;
				touchInfo.m_secondPoint = touchPoint;
			}
			view->onTouchUp(touchInfo);
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int mouseMoveView(int gID, char *name, int x, int y, int buttons, int clicks){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			FCTouchInfo touchInfo;
			FCPoint touchPoint = {x, y};
			touchInfo.m_clicks = clicks;
			if(buttons == 1){
				touchInfo.m_firstTouch = true;
				touchInfo.m_firstPoint = touchPoint;
			}else if(buttons == 2){
				touchInfo.m_secondTouch = true;
				touchInfo.m_secondPoint = touchPoint;
			}
			view->onTouchMove(touchInfo);
		}
		return 1;
	}else{
		return 0;
	}
}

extern "C" int mouseWheelView(int gID, char *name, int x, int y, int buttons, int clicks, int delta){
	std::map<int, FCNative*>::iterator sIter = m_natives.find(gID);
	if(sIter != m_natives.end()){
		FCNative *native = sIter->second;
		String strName = FCTran::stringToString(name);
		FCView *view = native->findView(strName);
		if(view){
			FCTouchInfo touchInfo;
			FCPoint touchPoint = {x, y};
			touchInfo.m_clicks = clicks;
			if(buttons == 1){
				touchInfo.m_firstTouch = true;
				touchInfo.m_firstPoint = touchPoint;
			}else if(buttons == 2){
				touchInfo.m_secondTouch = true;
				touchInfo.m_secondPoint = touchPoint;
			}
			touchInfo.m_delta = delta;
			view->onTouchWheel(touchInfo);
		}
		return 1;
	}else{
		return 0;
	}
}